#include "StdAfx.h"

#include "resource.h"

#include <fstream>
#include <cmath>
#include "waconsts.h"


//#include "DSAWindow_cos2.h"
#include "utilities.h"
#include "lib/fftw++.h"

#include "eeg_exceptions.h"
#include "datastore.h"
//#include "WaitBoxHelper.h"
#include "waitbox.h"

#include "DSACalculator.h"

using namespace std;

struct DSA_threadInvoke{
	DSACalculator* p;
	DSA_CalcParams params;
};

void DSA_Working_Thread( LPVOID pParam ){
	DSA_threadInvoke *ti=(DSA_threadInvoke* )pParam;
	ti->p->DoCalc(ti->params);
}


DSACalculator *DSACalculator::instance = 0;
DSACalculator::DSACalculator(void)
{
	isOutputReady = false;
	source = DataStore::GetInstance();
}

DSACalculator::~DSACalculator(void)
{
	reset();
}

/*int DSACalculator::EID2Index(int eid)
{
int ret=-1;
for(size_t i=0;i<out.size();i++){
if(out[i].eid==eid){
ret=i;break;
}
}
return ret;
}*/

int DSACalculator::StartCalc ( DSA_CalcParams p){
	//check params

	//DSA_CalcParams cp;
	p.signiture = signitureGenerator();
	isOutputReady = false;
	//out.clear();

	DSA_threadInvoke ti;
	ti.p = this;
	ti.params = p;

	wbd.SetPrompt(_T("Calculating DSA"));
	_beginthread(DSA_Working_Thread, 0, (void *)&ti);
	wbd.DoModal();
	int ret =FindInOut(p.signiture);
	if( ret == -1)
		return -1;
	else{
		isOutputReady = true;
		return p.signiture;
	}
}

void DSACalculator::DoCalc(const DSA_CalcParams p){
	const int SR = source->GetSamplingRate();

	//for(size_t i=0;i<p.regions.size()
	DSAOutput *tmpout = new DSAOutput();
	tmpout->signiture = p.signiture ;
	tmpout->startpt = p.startpt;
	tmpout->endpt = p.endpt ;

	const unsigned int n=SR*DSA_WINDOW_WIDTH;
	const unsigned int np=n/2+1;
	const unsigned int duration =(p.endpt - p.startpt)/SR;//in second
	const UINT upperPt = (UINT)DSA_MAX_FREQ*n/SR;
	double *f=FFTWdouble(n);
	Complex *g=FFTWComplex(np); 
	rcfft1d Forward(n,f,g); 

	tmpout->data.resize(duration);
	for(size_t i=0;i<duration;i++)
		tmpout->data[i].resize((UINT)upperPt,0.0);//allocation

	//int counter=0;
	
	for(size_t i=0;i<p.eids.size();i++)
	{
		//counter++;
		int index = source->GetElectrodeIndex(p.eids[i]);
		if( index == -1)
		{
			MessageBox(0,_T("Incorrect EID, ignored!"), _T("Error"),0);
			continue;
		}
		for(unsigned int time=0;time<duration-1;time++){
			for(unsigned int j=0; j < n; j++) source->GetRefData(index,j+time*SR,f[j]);//copy data

			Forward.fft(f,g);
			for(UINT k=0;k<upperPt ;k++)
				tmpout->data[time][k]+=g[k].real()*g[k].real()+g[k].imag()*g[k].imag();
		}
	}

	tmpout->max=0.0;
	for(unsigned int i=0;i<duration-1;i++)
		for(UINT j=0;j<upperPt ;j++){
			tmpout->data[i][j]/=p.eids.size();//get mean value
			tmpout->max =( tmpout->max<tmpout->data[i][j] && j!=0) ? tmpout->data[i][j] : tmpout->max;
		}
#ifdef _DEBUG
		ofstream ofs("dsa.txt");

		/*for(int i=0;i<m;i++)
		ofs << out[i].real() <<"   " << out[i].imag() << endl;
		ofs<<endl<<endl;*/
		for(unsigned int i=0;i<duration-1;i++){
			for(UINT j=0;j<upperPt;j++)
				ofs<<tmpout->data[i][j]<<" ";
			ofs<<endl;
		}
		ofs.close();
#endif

		FFTWdelete(f);
		FFTWdelete(g);

		out.push_back(tmpout);

		//WBH_Close(wb);
		PostMessage(wbd.m_hWnd,WM_CLOSE,0,0);
		//return 0;


}

bool DSACalculator::Export2File(LPCTSTR filename, int eid)
{

	return true;
}

int DSACalculator::FindInOut(int signiture) const 
{
	int ret=-1;
	for(size_t i=0;i<out.size();i++){
		if( out[i]->signiture == signiture){
			ret=i;break;
		}
	}
	return ret;
}